/*
 * Copyright (c) 2015-2019, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== empty.c ========
 */

/* For usleep() */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>
/* RTOS header files */
#include <ti/sysbios/BIOS.h>
/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/I2C.h>
#include <ti/drivers/I2C.h>
#include <ti/display/Display.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/I2C.h>
#include <ti/drivers/Timer.h>
#include <ti/drivers/ADC.h>

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
// #include <ti/drivers/Watchdog.h>
#include "Sensor_Sampling.h"
#include "frame_control_queue.h"
#include "packet_transmission.h"
#include "ssf.h"

extern Display_Handle display;
#define TAG "SensorSampling"
#ifndef DEBUG_PRINT_ENABLE
#define DEBUG_PRINT_ENABLE 1
#endif
#if DEBUG_PRINT_ENABLE
// Macro for debug print with file, function, and line number
// #define DEBUG_PRINT(fmt, ...) \
//     Display_printf(display, 0, 0, "[%s:%d:%s] " fmt, TAG, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define DEBUG_PRINT(fmt, ...) \
    Display_printf(display, 0, 0, "[%s:%d] " fmt, TAG, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...)
#endif

Event_Handle gEventHandle;
Clock_Handle gClockFeatureHandle;
Clock_Handle gClockMediumHandle;
Clock_Handle gClockHighHandle;
Clock_Handle gClockOverLengthHandle;

SensorVirtulData st_sensorvirtuldata;

STATIC UseOverFlow st_overflow = {0};   //对于超长时间，使用时间溢出计数模式
// 特征值定时器回调函数
void timerFeatureCallback(UArg arg) {
    Event_post(gEventHandle, EVENT_FEATURE);
}

// 中低频定时器回调函数
void timerMediumCallback(UArg arg) {
    Event_post(gEventHandle, EVENT_MEDIUM);
}

// 高频定时器回调函数
void timerHighCallback(UArg arg) {
    Event_post(gEventHandle, EVENT_HIGH);
}

// 超长定时器回调函数
void timerOverLengthCallback(UArg arg) {
    Event_post(gEventHandle, EVENT_OVERLENGTH);
}

static void Event_Config_Init(void)
{
    Event_Params eventParams;
    Event_Params_init(&eventParams);
    gEventHandle = Event_create(&eventParams, NULL);
    if (gEventHandle == NULL) {
        Display_printf(display, 0, 0, "事件创建失败!", NULL);
    }
    Smsgs_vibrateSampleConfig_t *vibrateconfig = Sensor_getVibrateSampleConfig();//获取采样参数句柄
    // 创建并配置特征值定时器
    Clock_Params clockFeatureParams;
    Clock_Params_init(&clockFeatureParams);
    clockFeatureParams.period = get_featur_times(vibrateconfig->Feature_sampleTimes) * TimeMultiplier;
    clockFeatureParams.startFlag = FALSE;  // 不立即启动
    clockFeatureParams.arg = (UArg)0;
    
    gClockFeatureHandle = Clock_create(timerFeatureCallback, 1000, &clockFeatureParams, NULL);
    if (gClockFeatureHandle == NULL) {
       Display_printf(display, 0, 0, "特征采集事件创建失败!", NULL);
    }
    
    // 创建并配置中频定时器
    if(vibrateconfig->Medium_sampleEna)
    {
        Clock_Params clockMediumParams;
        Clock_Params_init(&clockMediumParams);
        // clockMediumParams.period = get_meduim_times(vibrateconfig->Medium_sampleTimes) * TimeMultiplier;  
        clockMediumParams.period =60 * TimeMultiplier;       
        clockMediumParams.startFlag = FALSE;   // 不立即启动
        clockMediumParams.arg = (UArg)0;
    
        gClockMediumHandle = Clock_create(timerMediumCallback, 1000, &clockMediumParams, NULL);
        if (gClockMediumHandle == NULL) {
            Display_printf(display, 0, 0, "中低频采样事件创建失败!", NULL);
        }
    }

    // 创建并配置高频定时器
    if(vibrateconfig->High_sampleEna){
        Clock_Params clockHighmParams;
        Clock_Params_init(&clockHighmParams);
        if(get_high_times(vibrateconfig->High_sampleTimes) > 28800)//大于4小时
        {
            clockHighmParams.period = 3600 * TimeMultiplier; //使用1小时唤醒模式，累计计数
            st_overflow.HighFerq.useOverflowMode = true;
            st_overflow.HighFerq.TimesCount = get_high_times(vibrateconfig->High_sampleTimes) / 3600;
            st_overflow.HighFerq.TimesIndex = 0;
        }  
        else {
            clockHighmParams.period = get_high_times(vibrateconfig->High_sampleTimes) * TimeMultiplier; 
            st_overflow.HighFerq.useOverflowMode = false;
            st_overflow.HighFerq.TimesCount = 0;
            st_overflow.HighFerq.TimesIndex = 0;
        }
        clockHighmParams.startFlag = FALSE;   // 不立即启动
        clockHighmParams.arg = (UArg)0;
        
        gClockHighHandle = Clock_create(timerHighCallback, 1000, &clockHighmParams, NULL);
        if (gClockHighHandle == NULL) {
            Display_printf(display, 0, 0, "高频采样事件创建失败!", NULL);
        }
    }

    // 创建并配置超长定时器
    if(vibrateconfig->OverLength_sampleEna){
        Clock_Params clockOverLengrhmParams;
        Clock_Params_init(&clockOverLengrhmParams);
        clockOverLengrhmParams.period = 14400 * TimeMultiplier;       // 4小时计数
        st_overflow.OverLength.useOverflowMode = true;
        st_overflow.OverLength.TimesCount = vibrateconfig->OverLength_sampleTimes == 0 ? 3 : 6;
        st_overflow.OverLength.TimesIndex = 0;
        clockOverLengrhmParams.startFlag = FALSE;   // 不立即启动
        clockOverLengrhmParams.arg = (UArg)0;
        
        gClockOverLengthHandle = Clock_create(timerOverLengthCallback, 1000, &clockOverLengrhmParams, NULL);
        if (gClockOverLengthHandle == NULL) {
            Display_printf(display, 0, 0, "超长采样事件创建失败!", NULL);
        }
    }

    // 启动定时器
    Clock_start(gClockFeatureHandle);
    if(vibrateconfig->Medium_sampleEna)Clock_start(gClockMediumHandle);
    if(vibrateconfig->High_sampleEna)Clock_start(gClockHighHandle);
    if(vibrateconfig->OverLength_sampleEna)Clock_start(gClockOverLengthHandle);
}

void Event_Feature_work(void)
{
    SPIADC_ThreadStart(FEATURE_MODE);
    //sem_wait(&SampleEndSem);//等待采样结束
    Smsgs_vibrateSensorField_t *st_SensorsEigenvalue = Sensor_getVibrateSensorField();
    Smsgs_vibrateChannelConfig_t *st_channelconfg = Sensor_getVibrateChannelConfig();//获取振动通道配置参数
    Smsgs_vibrateChannelTempConfig_t *st_channelteamp = Sensor_getVibrateChannelTempConfig();//温度通道配置参数
    // Smsgs_sensorMsg_t sensor;
    //计算传感器数据
    Calculate_Eigenvalue(st_sensorvirtuldata.X_data.data,internal_adc_data.adcvalue[0],
        internal_adc_data.adcvalue[3],&st_SensorsEigenvalue->sensors[0],st_channelconfg[0],2000);//X
    Calculate_Eigenvalue(st_sensorvirtuldata.Y_data.data,internal_adc_data.adcvalue[1],
        internal_adc_data.adcvalue[4],&st_SensorsEigenvalue->sensors[1],st_channelconfg[1],2000);//Y
    Calculate_Eigenvalue(st_sensorvirtuldata.Z_data.data,internal_adc_data.adcvalue[2],
        internal_adc_data.adcvalue[5],&st_SensorsEigenvalue->sensors[2],st_channelconfg[2],2000);//Z
    //计算温度与电池电量
    st_SensorsEigenvalue->header.Bat = (float_t)(internal_adc_data.Bat * 0.0001f);
    if( st_SensorsEigenvalue->header.Bat >= 3.3)
    {
        st_SensorsEigenvalue->header.Bat = 100;
    }
    else {
        st_SensorsEigenvalue->header.Bat = (uint16_t)((st_SensorsEigenvalue->header.Bat / 3.3f) * 100);
    }
    st_SensorsEigenvalue->header.Template = (float_t)(internal_adc_data.Template / 2000.0f - st_channelteamp->zero * 0.01f) 
        * (st_channelteamp->sens * 0.01f);
    st_SensorsEigenvalue->header.Template = (8.194f - sqrt(81.017156f - st_SensorsEigenvalue->header.Template * 10.48f)) / (-0.0054f) + 30.0f; 
    //发送数据
    uint16_t fc = Smsgs_dataFields_accelThreeAxisSensor;
    FrameControlQueue_enqueue(fc);
    Util_setEvent(&Sensor_events, SENSOR_READING_TIMEOUT_EVT);
    Ssf_PostAppSem();
}

void Event_Medium_work(void)
{
    SPIADC_ThreadStart(MEDIUM_MODE);
    //sem_wait(&SampleEndSem);//等待采样结束
    //发送原始数据
    Smsgs_vibrateSampleConfig_t *vibrateconfig = Sensor_getVibrateSampleConfig();//获取采样参数句柄
    st_sensorvirtuldata.X_data.datatype = Low_Ferq_Xdata;//数据类型，X低频数据
    //低频采样数据长度；0:512;1:1024:2:4096;3:8192
    uint32_t dataLen = 0;
    if(vibrateconfig->Medium_sampleLength == 0){
        dataLen = 512;
    }
    else if(vibrateconfig->Medium_sampleLength == 1){
        dataLen = 1024;
    }
    else if(vibrateconfig->Medium_sampleLength == 2){
        dataLen = 4096;
    }
    else if(vibrateconfig->Medium_sampleLength == 3){
        dataLen = 8192;
    }
    dataLen += 2;  // 加上 datatype的长度2byte

    Display_printf(display, 0, 0, "Start X data");
    PacketTransmission_startRawTx(dataLen, (uint8_t *)&st_sensorvirtuldata.X_data, 64);//发送X轴数据
    //等待传输完成，错误则跳过
    Display_printf(display, 0, 0, "wait X end...");
    uint32_t event = PacketTransmission_waitRawTxStateEventBit(RAW_TX_EVENT_IDLE_MASK | RAW_TX_EVENT_ERROR_MASK, EventP_WAIT_FOREVER );
    if(event & RAW_TX_EVENT_ERROR_MASK){
        return;
    }
    Task_sleep(200);

    Display_printf(display, 0, 0, "Start Y data");
    st_sensorvirtuldata.Y_data.datatype = Low_Ferq_Ydata;//数据类型，Y低频数据
    PacketTransmission_startRawTx(dataLen, (uint8_t *)&st_sensorvirtuldata.Y_data, 64);//发送Y轴数据
    //等待传输完成，错误则跳过
    Display_printf(display, 0, 0, "Wait Y end...");
    event = PacketTransmission_waitRawTxStateEventBit(RAW_TX_EVENT_IDLE_MASK | RAW_TX_EVENT_ERROR_MASK, EventP_WAIT_FOREVER );
    if(event & RAW_TX_EVENT_ERROR_MASK){
        return;
    }
    Task_sleep(200);

    Display_printf(display, 0, 0, "Start Z data");
    st_sensorvirtuldata.Z_data.datatype = Low_ferq_Zdata;//数据类型，Z低频数据
    PacketTransmission_startRawTx(dataLen, (uint8_t *)&st_sensorvirtuldata.Z_data, 64);//发送Z轴数据
    //等待传输完成，错误则跳过
    Display_printf(display, 0, 0, "Wait Z end...");
    event = PacketTransmission_waitRawTxStateEventBit(RAW_TX_EVENT_IDLE_MASK | RAW_TX_EVENT_ERROR_MASK, EventP_WAIT_FOREVER );
    if(event & RAW_TX_EVENT_ERROR_MASK){
        return;
    }
    Task_sleep(200);
}

void Event_High_work(void)
{
    bool enawork = false;
    if(st_overflow.HighFerq.useOverflowMode)
    {
        if(st_overflow.HighFerq.TimesCount == st_overflow.HighFerq.TimesIndex)
        {
            enawork = true;
            st_overflow.HighFerq.TimesIndex = 0;
        }
        else {
            st_overflow.HighFerq.TimesIndex++;
            enawork = false;
        }
    }
    else {
        enawork = true;
    }
    if(enawork){
        SPIADC_ThreadStart(HIGH_MODE);
        //sem_wait(&SampleEndSem);//等待采样结束
        //发送原始数据
        Smsgs_vibrateSampleConfig_t *vibrateconfig = Sensor_getVibrateSampleConfig();//获取采样参数句柄
        st_sensorvirtuldata.Z_data.datatype = High_Ferq_Zdata;//数据类型，Z轴高频数据
        //高频采样长度,0:8192;1:16384;2:65536
        uint32_t dataLen = 0;
        if(vibrateconfig->High_sample_length == 0){
            dataLen = 8192;
        }
        else if(vibrateconfig->High_sample_length == 1){
            dataLen = 16384;
        }
        else if(vibrateconfig->High_sample_length == 2){
            dataLen = 65536;
        }
        dataLen += 2;  // 加上 datatype的长度2byte
        PacketTransmission_startRawTx(dataLen, (uint8_t *)&st_sensorvirtuldata.Z_data, 64);//发送Z轴数据
        uint32_t event = PacketTransmission_waitRawTxStateEventBit(RAW_TX_EVENT_IDLE_MASK | RAW_TX_EVENT_ERROR_MASK, EventP_WAIT_FOREVER );
        if(event & RAW_TX_EVENT_ERROR_MASK){
            return;
        }
    }
}

void Event_OverLength_work(void)
{
    bool enawork = false;
    if(st_overflow.OverLength.useOverflowMode)
    {
        if(st_overflow.OverLength.TimesCount == st_overflow.OverLength.TimesIndex)
        {
            enawork = true;
            st_overflow.OverLength.TimesIndex = 0;
        }
        else {
            st_overflow.OverLength.TimesIndex++;
            enawork = false;
        }
    }
    if(enawork){
        SPIADC_ThreadStart(OVERLENGTH_MODE);
        //sem_wait(&SampleEndSem);//等待采样结束
        //发送原始数据
    }
}

void mainTask(UArg arg0, UArg arg1) {
    // Clock_init();
    // Display_init();
    // GPIO_init();
    SPI_init();
    // I2C_init();
    // Timer_init();
    ADC_init();
    // GPIO_setConfig(CONFIG_GPIO_RLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);  // 暂时屏蔽，调试网络用
    GPIO_setConfig(CONFIG_GPIO_POWER, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); //电源控制
    Event_Config_Init();
    samplesem_init();
    // 允许系统进入低功耗模式
    // Power_releaseConstraint(PowerCC26XX_DISALLOW_STANDBY);  // 要先调用Power_setConstraint
    while (1) {
        // 等待外部事件
        uint32_t events = Event_pend(gEventHandle,Event_Id_NONE,ALL_EVENTS,BIOS_WAIT_FOREVER);
        Jdllc_states_t state = Jdllc_getProvState();
        DEBUG_PRINT("State: %d", state);
        if(state == Jdllc_states_joined || state == Jdllc_states_rejoined)
        {
            DEBUG_PRINT("In network");
        }
        else {
            DEBUG_PRINT("Not in network");
            Task_sleep(1000);
            continue;
        }

        //不允许进入低功耗，进行采样
        // Power_setConstraint(PowerCC26XX_DISALLOW_STANDBY);
        do{
            if(events & EVENT_FEATURE){
                // GPIO_toggle(CONFIG_GPIO_RLED);
                Event_Feature_work();
            }
            events = Event_pend(gEventHandle,Event_Id_NONE,ALL_EVENTS,1000);//再次读取，10ms超时
            if(events & EVENT_MEDIUM){
                // GPIO_toggle(CONFIG_GPIO_RLED);
                Event_Medium_work();
            }
            if(events & EVENT_HIGH){
                Event_High_work();
            }
        }while((events = Event_pend(gEventHandle,Event_Id_NONE,ALL_EVENTS,1000)));//再次读取，10ms超时

        // 处理完成后允许再次进入低功耗
        // Power_releaseConstraint(PowerCC26XX_DISALLOW_STANDBY);
        // Power_sleep(PowerCC26XX_STANDBY);
    }
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    Clock_init();
    Display_init();
    GPIO_init();
    SPI_init();
    I2C_init();
    Timer_init();
    ADC_init();
    GPIO_setConfig(CONFIG_GPIO_RLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
  //  GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    Event_Config_Init();
    samplesem_init();
    // 允许系统进入低功耗模式
    // Power_releaseConstraint(PowerCC26XX_DISALLOW_STANDBY);
    while (1) {
        // 等待外部事件
        uint32_t events = Event_pend(gEventHandle,Event_Id_NONE,ALL_EVENTS,BIOS_WAIT_FOREVER);
        //不允许进入低功耗，进行采样
        Power_setConstraint(PowerCC26XX_DISALLOW_STANDBY);
        if(events & EVENT_FEATURE){
            GPIO_toggle(CONFIG_GPIO_RLED);
            Event_Feature_work();
        }
        if(events & EVENT_MEDIUM){
            GPIO_toggle(CONFIG_GPIO_RLED);
            Task_sleep(5);
        }

        // 处理完成后允许再次进入低功耗
        Power_releaseConstraint(PowerCC26XX_DISALLOW_STANDBY);
        // Power_sleep(PowerCC26XX_STANDBY);
    }
}
